/*#include "windows.h"*/

#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <malloc.h>

#include "updater.h"

#define E() do{printf("->: %s : %d\n", __FUNCTION__, __LINE__);}while(0)
#define DD printf


static int parse_args(core_t * ps_core, int i_args, char ** ppc_args);
static void print_help(void);
static int open_update(core_t * core);
static int add_single_file(core_t * ps_core, node_t * ps_node);
/* static int add_file(core_t * core,  int i_argi, char ** ppc_args); */
static int add_dir(core_t * core,node_t *);
static int list_files(core_t * core);
static int install_package(core_t * core);
static int validate_update(core_t * ps_core);
static int extract_single_file(core_t * ps_core, node_t * ps_node);
static int search_files(core_t * ps_core, node_t * ps_node);
static int move_single_file(core_t * ps_core, node_t * ps_node);
static int del_single_file(core_t * ps_core, node_t * ps_node);
static int do_something(core_t * ps_core);
static int close_update(core_t * ps_core);
static int print_update_info(core_t * ps_core);

static core_t * core_new()
{
    core_t * ps_core;
    E();
    ps_core = malloc(sizeof(core_t));
    bzero(ps_core, sizeof(core_t));
    ps_core->files = que_create();

    return(ps_core);
}


static int core_destroy(core_t * ps_core)
{
    E();
    if (!ps_core) return(-1);
    que_destroy(ps_core->files);
    /* close(ps_core->i_fd_out); */
    close_update(ps_core);
    free(ps_core);
    return(0);
}


int main(int i_argn, char ** ppc_args)
{

    int i_rv;
    core_t * ps_core;
    E();

/*  memset(&s_ucore, 0, sizeof(ucore_t)); */

    if (i_argn < 2)
    {
        print_help();
        return(0);
    }

    ps_core = core_new();

    parse_args(ps_core, i_argn, ppc_args);

    printf("parsed args: update name = %s, number of args is %d\n", ps_core->pc_update_name, que_amount(ps_core->files));

    if (que_amount(ps_core->files) > 0)
    {
        node_t * ps_node = ps_core->files->list;

        while(ps_node)
        {
            printf("Command: %d, subject: %d, file: %s\n", ps_node->i_command, ps_node->i_subject, ps_node->data);
            ps_node=ps_node->next;
        }
        
    }
    else
    {
        printf("The comman set is empty\n");
        return(0);
    }

    i_rv = open_update(ps_core);

    if (i_rv)
    {
        printf("Can't open the update file\n");
        return(-1);
    }
    else
    {
        printf("Opened update\n");
    }

    do_something(ps_core);

    core_destroy(ps_core);
    return( 0 );
}


static void print_help()
{
    E();
    printf("\nUsage:\n");
    printf("up [ list    | -l ]   -u update_name\n");
    printf("up [ mv      | -m ]   -u update_name file_id / dir_id new_name\n");
    printf("up [ search  | -r ]   -u update_name word\n");
    printf("up [ add     | -a ] [ file  | -f ] -u update_name file1 [file2 ... fileN]\n");
    printf("up [ add     | -a ] [ dir   | -d ] -u update_name dir1  [dir2  ... dirN]\n");
    printf("up [ del     | -d ] [ file  | -f ] -u update_name file1 [file2 ... fileN]\n");
    printf("up [ del     | -d ] [ dir   | -d ] -u update_name dir1  [dir2  ... dirN]\n");
    printf("up [ set     | -f ] [ flag  | -s ] -u update_name id FLAG\n");
    printf("up [ clean   | -f ] [ flag  | -c ] -u update_name id FLAG\n");
    printf("up [ extract | -e ] [ file  | -f ] -u update_name id1 [id2 ... idN]\n");
    printf("\nThere also are short forms of commands:\n");
    printf("add file     =  -af\n");
    printf("add dir      =  -ad\n");
    printf("del file     =  -df\n");
    printf("del dir      =  -dd\n");
    printf("set flag     =  -sf\n");
    printf("clean flag   =  -cf\n");
    printf("extract file =  -ef\n");
}


static int command_gets_file(int i_command)
{
    E();
    switch(i_command)
    {
    case COMMAND_ADD:
    case COMMAND_DEL:
    case COMMAND_MV:
    case COMMAND_SEARCH:
    case COMMAND_SET:
    case COMMAND_CLEAN:
    case COMMAND_EXTRACT:
        return(1);
        break;
    }
    return(0);
}

static int parse_args(core_t * ps_core, int i_args, char ** ppc_args)
{
    int i_command = 0; /* command can be : add, del, list, extract, mv, flag */
    int i_subject;  /* subject it is a file, dir, update */
    int i = 1; /* Begin from ppc_args[1] */
    int i_len;
    node_t * ps_node;

    E();

    while (ppc_args[i])
    {
        /* Special case: -u, the update name. */

        if (!strcmp(ppc_args[i], "-u"))
        {
            i++; /* Next arg must be update name */
            if (!ppc_args[i])
            {
                printf("Please provide update name\n");
                return(-1);
            }
            i_len = strlen(ppc_args[i]);
            ps_core->pc_update_name = malloc(i_len + 1);
            memcpy(ps_core->pc_update_name,ppc_args[i], i_len);
            ps_core->pc_update_name[i_len] = '\0';
            i++; /* Done, jump to next */
            continue;
        }

        if (!strcmp(ppc_args[i], "add") || !strcmp(ppc_args[i], "-a"))      {i_command = COMMAND_ADD;      i_subject = 0; i++; continue;}
        if (!strcmp(ppc_args[i], "del") || !strcmp(ppc_args[i], "-d"))      {i_command = COMMAND_DEL;      i_subject = 0; i++; continue;}
        if (!strcmp(ppc_args[i], "list") || !strcmp(ppc_args[i], "-l"))     {i_command = COMMAND_LIST;     i_subject = 1; }
        if (!strcmp(ppc_args[i], "info") || !strcmp(ppc_args[i], "-i"))     {i_command = COMMAND_INFO;     i_subject = 1; }
        if (!strcmp(ppc_args[i], "search") || !strcmp(ppc_args[i], "-r"))   {i_command = COMMAND_SEARCH;   i_subject = 0; i++; continue;}
        if (!strcmp(ppc_args[i], "set") || !strcmp(ppc_args[i], "-s"))      {i_command = COMMAND_SEARCH;   i_subject = 0; i++; continue;}
        if (!strcmp(ppc_args[i], "clean") || !strcmp(ppc_args[i], "-s"))    {i_command = COMMAND_SEARCH;   i_subject = 0; i++; continue;}
        if (!strcmp(ppc_args[i], "extract") || !strcmp(ppc_args[i], "-e"))  {i_command = COMMAND_EXTRACT;  i_subject = 0; i++; continue;}

        if (!strcmp(ppc_args[i], "-af")) {i_command = COMMAND_ADD;    i_subject = SUBJECT_FILE; i++; continue;}
        if (!strcmp(ppc_args[i], "-ad")) {i_command = COMMAND_ADD;    i_subject = SUBJECT_DIR;  i++; continue;}
        if (!strcmp(ppc_args[i], "-df")) {i_command = COMMAND_DEL;    i_subject = SUBJECT_FILE; i++; continue;}
        if (!strcmp(ppc_args[i], "-dd")) {i_command = COMMAND_DEL;    i_subject = SUBJECT_DIR;  i++; continue;}
        if (!strcmp(ppc_args[i], "-sf")) {i_command = COMMAND_SET;    i_subject = SUBJECT_FLAG; i++; continue;}
        if (!strcmp(ppc_args[i], "-cf")) {i_command = COMMAND_CLEAN;  i_subject = SUBJECT_FLAG; i++; continue;}
        if (!strcmp(ppc_args[i], "-ef")) {i_command = COMMAND_EXTRACT;i_subject = SUBJECT_FLAG; i++; continue;}

        if (i_command)
        {
            if (!strcmp(ppc_args[i], "file") || !strcmp(ppc_args[i], "-f"))     {i_subject = SUBJECT_FILE; i++; continue;}
            if (!strcmp(ppc_args[i], "dir") || !strcmp(ppc_args[i], "-d"))      {i_subject =  SUBJECT_DIR; i++; continue;}
            if (!strcmp(ppc_args[i], "flag") || !strcmp(ppc_args[i], "-s"))     {i_subject =  SUBJECT_FLAG;i++; continue;}
        }

        /* Now suppose we parsed all commands / subjects. */
        if (i_command && i_subject)
        {
            /* All right. Here I know what the file is: directory or file */
            /* greate new node */

            ps_node = node_create(NULL);

            if (!ps_node)
            {
                printf("Can't allocate memory for node\n");
                return(-1);
            }

            ps_node->i_command = i_command;
            ps_node->i_subject = i_subject;

            if (command_gets_file(i_command))
            {
                i_len = strlen(ppc_args[i]);
                ps_node->data = malloc(i_len + 1);
                memcpy(ps_node->data, ppc_args[i], i_len);
            }
            
            que_add_node(ps_core->files, ps_node);
        }

        else printf("i_command: %d i_subject: %d ppc_args[i]: %s", i_command, i_subject, ppc_args[i]);

        i++;
    }
    return(0);
}


/* This function set the file descriptor of update file to a prefefined point: */
/* To updater main header, to tags, to sets, to first file, to "new file" what is end of last file  */
/* See defines of group LSEEK_ to find all prefefined points */
static int lseek_to(core_t * ps_core, int i_where)
{
    update_t upd;
    off_t off_i;

    E();

    switch (i_where)
    {
    case LSEEK_BEGIN:
        off_i = lseek(ps_core->i_fd_out, 0, SEEK_SET);
        break;

    case LSEEK_END:
        off_i = lseek(ps_core->i_fd_out, 0, SEEK_END);
        break;

    case LSEEK_NAME:
        off_i = lseek(ps_core->i_fd_out, sizeof(upd.magic), SEEK_SET);
        break;

    case LSEEK_DESC:
        off_i = lseek(ps_core->i_fd_out, sizeof(upd.magic) + sizeof(upd.name), SEEK_SET);
        break;

    case LSEEK_U_HEADER:
        off_i = lseek(ps_core->i_fd_out, 0, SEEK_SET);
        break;

    case LSEEK_TAGS:
        if(0 == ps_core->ps_update->tags)
            return(-1);
        off_i = lseek(ps_core->i_fd_out, ps_core->ps_update->tags, SEEK_SET);
        break;

    case LSEEK_SETS:
        if(0 == ps_core->ps_update->sets)
            return(-1);
        off_i = lseek(ps_core->i_fd_out, ps_core->ps_update->sets, SEEK_SET);
        break;

    case LSEEK_CODE:
        if(0 == ps_core->ps_update->code)
            return(-1);
        off_i = lseek(ps_core->i_fd_out, ps_core->ps_update->code, SEEK_SET);
        break;

    case LSEEK_LAST:
        {
            /* file_t fh; */
            /* Run to last file, file by file */
            off_i = lseek(ps_core->i_fd_out, sizeof(update_t), SEEK_SET);
            /* Read file header */
        }
        break;

    case LSEEK_FIRST:
        /* Run to last file, file by file */
        off_i = lseek(ps_core->i_fd_out, sizeof(update_t), SEEK_SET);
        break;
    }

    if ( off_i < 0 ) return(-1);

    return(0);
}


static update_t * create_update_t(core_t * ps_core)
{
    update_t * ps_update = malloc(sizeof(update_t));

    E();

    if (!ps_update) return(NULL);

    bzero(ps_update, sizeof(update_t));
    ps_update->magic = 310258322;
    ps_update->id = 1;
    strcpy(ps_update->name, "Nim");
    strcpy(ps_update->desc, "Nom");

    return(ps_update);
}


/* Read header from file. Validate it. */
static int validate_update(core_t * ps_core)
{
    update_t s_update;
    off_t i_current = lseek(ps_core->i_fd_out, 0, SEEK_CUR);

    E();

    lseek(ps_core->i_fd_out, 0, SEEK_SET);
    read(ps_core->i_fd_out, &s_update, sizeof(s_update));

    lseek(ps_core->i_fd_out, i_current, SEEK_SET);
    
    if (s_update.magic != UPDATE_MAGIC)
    {
        return(-1);
    }
    
    ps_core->ps_update = (update_t * ) malloc(sizeof(update_t));
    memcpy(ps_core->ps_update, &s_update, sizeof(update_t));

    return(0);
}



static int close_update(core_t * ps_core)
{
    int i;

    /* First, write out ps_update structure if the update opened for writing  */
    if(ps_core->i_fd_flags & O_WRONLY)
    {
        lseek_to(ps_core, LSEEK_U_HEADER);
        i = write(ps_core->i_fd_out, ps_core->ps_update, sizeof(update_t));
    }

    /* Close file descriptor */
    close(ps_core->i_fd_out);

    ps_core->i_fd_flags = 0;
    ps_core->i_fd_out = -1;

    return(0);
}

static int open_update(core_t * ps_core)
{
    struct stat s_stat;
    node_t * ps_node = ps_core->files->list;
    update_t * ps_update;
    int i;
    ps_core->i_fd_flags = 0;

    E();

    /* Scan all nodes. Detect the action, build flags and type of opening (read / write / read+write) */
    while (ps_node)
    {
        switch (ps_node->i_command)
        {
        case COMMAND_ADD:
        case COMMAND_DEL:
        case COMMAND_MV:
        case COMMAND_SET:
        case COMMAND_CLEAN:
            ps_core->i_fd_flags |= O_APPEND | O_CREAT | O_WRONLY | O_RDONLY;
            printf("Flags: O_APPEND | O_CREAT | O_WRONLY | O_RDONLY\n");
            break;

        case COMMAND_EXTRACT:
        case COMMAND_SEARCH:
        case COMMAND_LIST:
        case COMMAND_INFO:
            ps_core->i_fd_flags |= O_RDONLY;
            printf("Flags: O_RDONLY\n");
            break;
        }

        ps_node = ps_node->next;
    }

    /* Before all, examine the update header (if exists) */
    
    if (!stat(ps_core->pc_update_name, &s_stat))
    {
        ps_core->i_fd_out = open(ps_core->pc_update_name, O_RDONLY);
        if (ps_core->i_fd_out && validate_update(ps_core))
        {
            printf("Wrong magic\n");
            return(-1);
        }

        /* close(ps_core->i_fd_out); */
        close_update(ps_core);
    }
    else /* No update. Create it. */
    {
        ps_core->i_fd_out = open(ps_core->pc_update_name, O_WRONLY | O_CREAT, 0666);

        if (ps_core->i_fd_out < 0)
        {
            perror("Can't open new update in writing mode: ");
            exit(-1);
        }
        ps_update = create_update_t(ps_core);

        i = write(ps_core->i_fd_out, ps_update, sizeof(update_t));
        if (i != sizeof(update_t))
        {
            perror("Can't write updater header to new update file:");
            free(ps_update);
            core_destroy(ps_core);
            exit(-1);
        }

        ps_core->ps_update = ps_update;
        /* close (ps_core->i_fd_out); */
        close(ps_core->i_fd_out);
    }

    /* First of all stat the file. If it doesn't exist I need create the update header */

    if (ps_core->i_fd_flags & O_CREAT)
    {
        ps_core->i_fd_out = open(ps_core->pc_update_name, ps_core->i_fd_flags, 0666);
    }
    else
        ps_core->i_fd_out = open(ps_core->pc_update_name, ps_core->i_fd_flags);

    return(0);
}


/* stat the file, returns the filled file_t structure */
static int stat_file(core_t * ps_core, char * pc_file, file_t * ps_file_header)
{
    struct stat s_st;
    char * pc_last_slash;

    E();

    if (!ps_file_header || ! pc_file)
    {
        printf("Wrong arg : %p || %p\n", (void *) pc_file, (void *) ps_file_header);    
        return(-1);
    }

    if ( stat(pc_file, &s_st) )
    {
        printf("stat fell\n");
        perror("couldn't stat file : ");    
        return(-1);
    }

    bzero(ps_file_header, sizeof(file_t));

    if (S_ISREG(s_st.st_mode))  ps_file_header->flags = FLAG_REG;
    if (S_ISDIR(s_st.st_mode))  ps_file_header->flags = FLAG_DIR;
    if (S_ISCHR(s_st.st_mode))  ps_file_header->flags = FLAG_CHR;
    if (S_ISBLK(s_st.st_mode))  ps_file_header->flags = FLAG_BLK;
    if (S_ISFIFO(s_st.st_mode))  ps_file_header->flags = FLAG_FIFO;
    if (S_ISLNK(s_st.st_mode))  ps_file_header->flags = FLAG_LINK;

    ps_file_header->group = s_st.st_gid;
    ps_file_header->owner = s_st.st_uid;
    ps_file_header->perm = s_st.st_mode;

    /* If the file is reg file or link - save the size */
    if (ps_file_header->flags & (FLAG_REG | FLAG_LINK)) ps_file_header->size = s_st.st_size;

    /* Connect file name to core struct */
    ps_file_header->name = pc_file;

    /* Split the file to name and path */
    if (ps_file_header->flags & (FLAG_REG | FLAG_LINK | FLAG_BLK | FLAG_CHR))
    {
        pc_last_slash=rindex(pc_file, '/');
        if (pc_last_slash)
        {
            ps_file_header->name_len =  strlen(pc_file) - (pc_last_slash - pc_file);
            ps_file_header->dir_len = pc_last_slash - pc_file;        
        }
        else  ps_file_header->name_len = strlen(pc_file);
    }

    if (ps_file_header->flags & FLAG_DIR)  ps_file_header->dir_len = strlen(pc_file);

    return(0);
}


static unsigned int get_id(core_t * ps_core)
{
#if 0    
    file_t s_fh;
    int i;
    static int i_id = 1;
    off_t i_current;
#endif    

    E();

    return(ps_core->ps_update->id++);

#if 0    
    if (i_id  > 1) return(++i_id);

    /* Save current offset */
    i_current = lseek(ps_core->i_fd_out, 0, SEEK_CUR);

    /* Set fd stream pointer to the beginning */
    /* lseek(ps_core->i_fd_out, 0, SEEK_SET); */
    lseek_to(ps_core, LSEEK_FIRST);

    /* read header by header, read id from heade and search for max id */
    do
    {
        i = read(ps_core->i_fd_out, &s_fh,sizeof(file_t));
        if (i != sizeof(file_t))
        {
            lseek(ps_core->i_fd_out, i_current, SEEK_SET);
            return i_id;
        }

        if (s_fh.id >= i_id) i_id = s_fh.id + 1;

        /* Jump to next */

        if ( (off_t) -1 == lseek(ps_core->i_fd_out, s_fh.size + s_fh.dir_len + s_fh.name_len, SEEK_CUR) )
        {
            lseek(ps_core->i_fd_out, i_current, SEEK_SET);    
            return i_id;
        }

    } while (sizeof(file_t) == i);

    lseek(ps_core->i_fd_out, i_current, SEEK_SET);
#endif    
    return(-1);
}


/* This function is a dispatcher. After parsing the argumet list */
/* and opening update file it runs on list of files / actions */ 
/* and calls appropriate fuction(s) */

static int do_something(core_t * ps_core)
{
    node_t * ps_node;
    ps_node = node_extract(ps_core->files);

    E();

    while(ps_node)
    {
        /* do switch by comand / subject */
        switch(ps_node->i_command)
        {
        case COMMAND_ADD:
            add_single_file(ps_core, ps_node);
            break;
        case COMMAND_DEL:
            del_single_file(ps_core, ps_node);
            break;
        case COMMAND_LIST:
            list_files(ps_core);
            break;
        case COMMAND_MV:
            move_single_file(ps_core, ps_node);
            break;
        case COMMAND_SEARCH:
            search_files(ps_core, ps_node);
            break;
        case COMMAND_EXTRACT:
            extract_single_file(ps_core, ps_node);
            break;
        case COMMAND_INFO:
            print_update_info(ps_core);
            break;

        }
        ps_node = node_extract(ps_core->files);
    }
    return(0);
}

static int add_single_file(core_t * ps_core /*, char * pc_file, char * pc_copy_buffer, int i_copy_buffer_size */, node_t * ps_node)
{
    struct stat s_st;
    file_t s_fh;
    int i_fd_in;
    size_t i_r;
    size_t i_w;
    off_t i_header_offset;
/*    off_t i_current; */
    off_t i_size;

    int i_copy_buffer_size = 512 * 1024;
    char * pc_copy_buf;

    E();


    /* Copy 512 K per circle. If it can't - try less */
    do 
    {
        pc_copy_buf = malloc(i_copy_buffer_size);
        i_copy_buffer_size /= 2;
    } while (NULL == pc_copy_buf && i_copy_buffer_size > 1);

    if (! pc_copy_buf)
    {
        printf("Can't allocate memory\n");
        return(-1);
    }


    if ( 0 != stat_file(ps_core, ps_node->data, &s_fh) )
    {
        printf("Couldn't add file %s\n", ps_node->data);
        printf("fh.name : %s\n", s_fh.name);
        return(-1);
    }

    s_fh.id= get_id(ps_core);

    if (s_fh.flags & FLAG_REG) i_fd_in = open(ps_node->data, O_RDONLY);

    if (i_fd_in < 0)
    {
        /* Can't open the file */
        printf("couldn't open for reading file %s\n", ps_node->data);
        return(-1);
    }

    /* Go to the end of file */
//    lseek(ps_core->i_fd_out, SEEK_END, 0);
    lseek_to(ps_core, LSEEK_END);
    

    /* Save current offset */
    i_header_offset = lseek(ps_core->i_fd_flags, 0, SEEK_CUR);

    /* Write file header */
    i_w = write(ps_core->i_fd_out, &s_fh, (size_t) sizeof(file_t));



    if ( i_w != (size_t) sizeof(file_t) )
    {
        printf( "couldn't write the header of file %s : %d when header is %d\n", ps_node->data, i_w, sizeof(file_t));
        /* Here I need rescue the file: a reverse */
    }



    /* write out the filename: its len is file_name + dir_name */
    i_w = write(ps_core->i_fd_out, s_fh.name, s_fh.dir_len + s_fh.name_len);
    if (i_w != s_fh.dir_len + s_fh.name_len)
    {
        printf("Fell writing file name\n");
    }

    if ( ! (s_fh.flags & FLAG_REG)) return(0);

    /* Read from the file and write to update */
    do
    {
        i_r = read(i_fd_in, pc_copy_buf, i_copy_buffer_size);
        /* printf("Read from input : %d bytes\n", i); */
        if (i_r)
        {
            i_w = write(ps_core->i_fd_out, pc_copy_buf, i_r);
            if (i_w != i_r)  printf("wrong: read %d bytes but written %d\n", i_r, i_w);
        }
    } while (i_r > 0);

    close(i_fd_in);
    return(0);
}


#if 0
static int add_file(core_t * ps_core, int i_argi, char ** ppc_args)
{
    char * pc_file;
    int i_file_index = 4;
    int i_copy_buffer_size = 512 * 1024;
    char * pc_copy_buf;

    /* Copy 512 K per circle. If it can't - try less */
    do 
    {
        pc_copy_buf = malloc(i_copy_buffer_size);
        i_copy_buffer_size /= 2;
    } while (NULL == pc_copy_buf && i_copy_buffer_size > 1);

    if (! pc_copy_buf)
    {
        printf("Can't allocate memory\n");
        return(-1);
    }

    do
    {
        pc_file = ppc_args[i_file_index];
        i_file_index++;

        printf("+F: %s\n", pc_file);
        add_single_file(ps_core, pc_file, pc_copy_buf,i_copy_buffer_size);

        pc_file = ppc_args[i_file_index];
    } while (ppc_args[i_file_index]);

    if (pc_copy_buf) free(pc_copy_buf);

    return(0);
}
#endif



/* scans directory, returns list offiles in the directory and its subdirectories */
static int scan_dir(core_t * ps_core, node_t * ps_node)
{
    E();
    return(0);
}


static int add_dir(core_t * ps_core, node_t * ps_node)
{
    E();
    printf("+D: \n");
    return(0);
}


static int list_files(core_t * ps_core)
{
    file_t s_fh;
    int i;
    char ac_filename[FILENAME_MAX];

    E();

    printf("Reding file list\n");

    i = lseek_to(ps_core, LSEEK_FIRST);
    if (i) return(i);
    /* read header by header, read id from heade and search for max id */

    printf("ID    | SIZE\t\t| FILENAME\n");
    printf("==================================\n");

    do
    {
        i = read(ps_core->i_fd_out, &s_fh,sizeof(file_t));

        if (i < sizeof(file_t)) return(0);

        i = read(ps_core->i_fd_out, ac_filename,  s_fh.dir_len + s_fh.name_len);
        ac_filename[i] = '\0';
        printf("%.5d : %d \t\t%s\n", s_fh.id, (int) s_fh.size, ac_filename);

        /* Jump to next */

        DD("Jumps %d bytes ahead\n", s_fh.size);
        i = lseek(ps_core->i_fd_out, s_fh.size, SEEK_CUR );
        DD("Jump status: %d\n", i);
        if ( (off_t) -1 == i ) return 0;

    } while (1);

    return(0);
}


static int print_update_info(core_t * ps_core)
{
    printf("Version: %d.%d\n", ps_core->ps_update->major, ps_core->ps_update->minor);
    printf("Name: %s\n", ps_core->ps_update->name);
    printf("Desc: %s\n", ps_core->ps_update->desc);
    printf("Max id: %d\n", ps_core->ps_update->id);
    printf("Size: %d\n", ps_core->ps_update->size);

    printf("Tags offset/size: %d/%d\n", ps_core->ps_update->tags, ps_core->ps_update->tags_size);
    printf("Sets offset/size: %d/%d\n", ps_core->ps_update->sets, ps_core->ps_update->sets_size);
    printf("Code offset/size: %d/%d\n", ps_core->ps_update->code, ps_core->ps_update->code_size);

    return(0);
}


static int install_package(core_t * ps_core)
{
    E();
    return(0);
}


static int extract_single_file(core_t * ps_core, node_t * ps_node)
{
    E();
    return(0);
}


static int search_files(core_t * ps_core, node_t * ps_node)
{
    E();
    return(0);
}


static int move_single_file(core_t * ps_core, node_t * ps_node)
{
    E();
    return(0);
}

static int del_single_file(core_t * ps_core, node_t * ps_node)
{
    E();
    return(0);
}
